/**
 * @see https://x6.antv.antgroup.com/examples/showcase/practices#orgchart
 * @usage
 * import xcFlowUtils from '@/library/xcore/js/XcFlowUtils';
 * 
 * <div id="container"></div>
 * let graph = xcFlowUtils.initGraph('container');
 * const nodes = [xcFlowUtils.createNode(graph, '初始状态', '发起人：任何人')];
 * const edges = [xcFlowUtils.createEdge(graph, nodes[0], nodes[1])];
 * xcFlowUtils.renderGraph(graph, [...nodes, ...edges]);
 */
import dagre from 'dagre'
import {
	Graph,
	Cell,
	Node,
	Dom
} from '@antv/x6'
import insertCss from 'insert-css'

let xcFlowUtils_vm = null;
export default {
	appInit: function(vm) {
		let that = this;
		xcFlowUtils_vm = vm;
	},
	initGraph: function(domid) {
		let that = this;

		insertCss(`
		  .x6-cell {
		    cursor: default;
		  }
		  .x6-node .btn {
		    cursor: pointer;
		  }
		`);

		const graph = new Graph({
			container: document.getElementById(domid),
			background: {
				color: '#F2F7FA',
			},
			autoResize: true,
			panning: true,
			mousewheel: true,
			background: {
				color: '#F2F7FA',
			},
			grid: {
				visible: true,
				type: 'doubleMesh',
				args: [{
						color: '#eee', // 主网格线颜色
						thickness: 1, // 主网格线宽度
					},
					{
						color: '#ddd', // 次网格线颜色
						thickness: 1, // 次网格线宽度
						factor: 4, // 主次网格线间隔
					},
				],
			},
		});
		that.register();
		return graph;
	},
	renderGraph: function(graph, nodesAndedges) {
		let that = this;
		graph.resetCells(nodesAndedges);
		that.layout(graph,"TB");
		graph.centerContent();
		graph.zoomTo(0.8);
	},
	createEdge(graph, source, target) {
		let that = this;
		return graph.createEdge({
			shape: 'xstatus-edge',
			source: {
				cell: source.id
			},
			target: {
				cell: target.id
			},
			attrs: {
			    line: {
			      targetMarker: 'block',
			    },
			  },
		});
	},
	createStatusNode: function(graph, title, content) {
		//console.log('createStatusNode', title, content);
		let that = this;
		return graph.createNode({
			shape: 'xstatus-node',
			attrs: {
				'.title': {
					text: Dom.breakText(title, {
						width: 160,
						height: 45
					}),
				},
				'.content': {
					text: Dom.breakText(content, {
						width: 160,
						height: 45
					}),
				},
			},
		})
	},
	createLogicNode: function(graph, title, content) {
		//console.log('createLogicNode', title, content);
		let that = this;
		return graph.createNode({
			shape: 'xlogic-node',
			attrs: {
				'.title': {
					text: Dom.breakText(title, {
						width: 160,
						height: 45
					}),
				},
				'.content': {
					text: Dom.breakText(content, {
						width: 160,
						height: 45
					}),
				},
			},
		})
	},	
	bindEvent: function(graph, eventName, func){
		let that = this;
		graph.on(eventName, ({
			e,
			node
		}) => {
			e.stopPropagation()
			func(node);
		});	
	},
	_searchParentNodeId(graph, nodeId) {
		let that = this;
		const edges = graph.getEdges()
		for(let index in edges){
			const edge = edges[index];
			const source = edge.getSource()
			const target = edge.getTarget()
			if(target.cell == nodeId){
				return source.cell;
			}
		}
		return null;
	},
	// dir: LR RL TB BT
	layout: function(graph, dir) {
		let that = this;
		const nodes = graph.getNodes()
		const edges = graph.getEdges()
		const g = new dagre.graphlib.Graph()

		g.setGraph({
			rankdir: dir,
			align: '',
			nodesep: 16,
			ranksep: 16,
		})
		g.setDefaultEdgeLabel(() => ({}))

		const width = 360
		const height = 120
		nodes.forEach((node) => {
			g.setNode(node.id, {
				width,
				height
			})
		})

		edges.forEach((edge) => {
			const source = edge.getSource()
			const target = edge.getTarget()
			g.setEdge(source.cell, target.cell)
		})

		dagre.layout(g)

		g.nodes().forEach((id) => {
			const node = graph.getCellById(id)
			const parentNodeId = that._searchParentNodeId(graph, id);
			const pos = g.node(id);
			if (parentNodeId==null && node) {
				node.position(pos.x, pos.y)
			}else if(parentNodeId!=null && node){
				// 处理了默认Dagre流程图中，默认分支靠下排序的问题
				// 根据父节点的位置+140（目前有多个节点，存在BUG，可能选取更高的来计算）
				// console.log("parentNode", pos.y, g.node(parentNodeId).y);
				node.position(pos.x, g.node(parentNodeId).y + 140)
			}
		})
	},
	register: function() {
		let that = this;
		Graph.registerEdge(
			'xstatus-edge', {
				zIndex: -1,
				attrs: {
					line: {
						strokeWidth: 2,
						stroke: '#A2B1C3',
						sourceMarker: null,
						targetMarker: null,
					},
				},
			},
			true,
		);

		Graph.registerNode(
			'xstatus-node', {
				width: 260,
				height: 88,
				markup: [{
						tagName: 'rect',
						attrs: {
							class: 'card',
						},
					},
					{
						tagName: 'text',
						attrs: {
							class: 'title',
						},
					},
					{
						tagName: 'text',
						attrs: {
							class: 'content',
						},
					},
					// important: 后续扩展多logic模式(不可删除)
					// {
					// 	tagName: 'g',
					// 	attrs: {
					// 		class: 'btn branch',
					// 	},
					// 	children: [{
					// 			tagName: 'circle',
					// 			attrs: {
					// 				class: 'branch',
					// 			},
					// 		},
					// 		{
					// 			tagName: 'text',
					// 			attrs: {
					// 				class: 'branch',
					// 			},
					// 		},
					// 	],
					// },
					{
						tagName: 'g',
						attrs: {
							class: 'btn add',
						},
						children: [{
								tagName: 'circle',
								attrs: {
									class: 'add',
								},
							},
							{
								tagName: 'text',
								attrs: {
									class: 'add',
								},
							},
						],
					},
					{
						tagName: 'g',
						attrs: {
							class: 'btn del',
						},
						children: [{
								tagName: 'circle',
								attrs: {
									class: 'del',
								},
							},
							{
								tagName: 'text',
								attrs: {
									class: 'del',
								},
							},
						],
					},
				],
				attrs: {
					'.card': {
						rx: 10,
						ry: 10,
						refWidth: '100%',
						refHeight: '100%',
						fill: '#5F95FF',
						stroke: '#5F95FF',
						strokeWidth: 1,
						pointerEvents: 'visiblePainted',
						event: 'xstatus node:click',
					},
					'.title': {
						refX: 0.05,
						refY: 0.12,
						fill: '#fff',
						fontFamily: 'Courier New',
						fontWeight: '600',
						textAnchor: 'start',
					},
					'.content': {
						refX: 0.05,
						refY: 0.40,
						fill: '#fff',
						fontFamily: 'Arial',
						fontSize: 13,
						textAnchor: 'start',
					},
					'.btn.add': {
						refDx: -16,
						refY: 16,
						event: 'xstatus node:add',
					},
					'.btn.branch': {
						refDx: -44,
						refY: 16,
						event: 'xstatus node:branch',
					},
					'.btn.del': {
						refDx: -72,
						refY: 16,
						event: 'xstatus node:delete',
					},
					'.btn > circle': {
						r: 10,
						fill: 'transparent',
						stroke: '#fff',
						strokeWidth: 1,
					},
					'.btn.add > text': {
						fontSize: 20,
						fontWeight: 800,
						fill: '#fff',
						x: -5.5,
						y: 7,
						fontFamily: 'Times New Roman',
						text: '+',
					},
					'.btn.branch > text': {
						fontSize: 14,
						fontWeight: 300,
						fill: '#fff',
						x: -3.5,
						y: 6,
						fontFamily: 'Courgette',
						text: 'Y',
					},
					'.btn.del > text': {
						fontSize: 28,
						fontWeight: 500,
						fill: '#fff',
						x: -4.5,
						y: 6,
						fontFamily: 'Times New Roman',
						text: '-',
					},
				},
			},
			true,
		);
		
		
		Graph.registerNode(
			'xlogic-node', {
				width: 260,
				height: 88,
				markup: [{
						tagName: 'rect',
						attrs: {
							class: 'card',
						},
					},
					{
						tagName: 'text',
						attrs: {
							class: 'title',
						},
					},
					{
						tagName: 'text',
						attrs: {
							class: 'content',
						},
					},
					{
						tagName: 'g',
						attrs: {
							class: 'btn add',
						},
						children: [{
								tagName: 'circle',
								attrs: {
									class: 'add',
								},
							},
							{
								tagName: 'text',
								attrs: {
									class: 'add',
								},
							},
						],
					},
					{
						tagName: 'g',
						attrs: {
							class: 'btn del',
						},
						children: [{
								tagName: 'circle',
								attrs: {
									class: 'del',
								},
							},
							{
								tagName: 'text',
								attrs: {
									class: 'del',
								},
							},
						],
					},
				],
				attrs: {
					'.card': {
						rx: 10,
						ry: 10,
						refWidth: '100%',
						refHeight: '100%',
						fill: '#FFFFFF',
						stroke: '#5F95FF',
						strokeWidth: 1,
						pointerEvents: 'visiblePainted',
						event: 'xlogic node:click',
					},
					'.title': {
						refX: 0.05,
						refY: 0.12,
						fill: '#5F95FF',
						fontFamily: 'Courier New',
						fontWeight: '600',
						textAnchor: 'start',
					},
					'.content': {
						refX: 0.05,
						refY: 0.40,
						fill: '#5F95FF',
						fontFamily: 'Arial',
						fontSize: 13,
						textAnchor: 'start',
					},
					'.btn.add': {
						refDx: -16,
						refY: 16,
						event: 'xlogic node:add',
					},
					'.btn.del': {
						refDx: -44,
						refY: 16,
						event: 'xlogic node:delete',
					},
					'.btn > circle': {
						r: 10,
						fill: 'transparent',
						stroke: '#5F95FF',
						strokeWidth: 1,
					},
					'.btn.add > text': {
						fontSize: 20,
						fontWeight: 800,
						fill: '#5F95FF',
						x: -5.5,
						y: 7,
						fontFamily: 'Times New Roman',
						text: '+',
					},
					'.btn.branch > text': {
						fontSize: 14,
						fontWeight: 200,
						fill: '#5F95FF',
						x: -4.0,
						y: 6.5,
						fontFamily: 'Courgette',
						text: 'Y',
					},
					'.btn.del > text': {
						fontSize: 28,
						fontWeight: 500,
						fill: '#5F95FF',
						x: -4.5,
						y: 6,
						fontFamily: 'Times New Roman',
						text: '-',
					},
				},
			},
			true,
		);
	}

}